package com.py.credit.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URL;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

/**
 * @author MaoLiliang
 * @version 1.0
 * @date 2020/11/28 19:36
 */

public class Html2Pdf {
    /**
     * 项目中自带字体的目录
     */
    public static final String FONT_PATH_SONG = "template/simhei.ttf";

    public static final String SourceHanSansCN_Regular_TTF = "template/SourceHanSansCN-Regular.ttf";

    private static Configuration config = null;

    static {
        config = new Configuration();
        //freemarker的模板目录
        try {
            config.setDirectoryForTemplateLoading(new File(PathUtil.getCurrentPath()));
            config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            config.setLogTemplateExceptions(false);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成PDF
     *
     * @param data         数据对象
     * @param templatePath 模板路径
     * @param destPath     目标路径
     * @param fileName     文件名
     * @return
     */
    public static boolean builderPdf(Map<String, Object> data, String templatePath, String destPath, String fileName) {
        boolean flag = true;
        try {
            String html = freeMarkerRender(data, templatePath);
            if (!destPath.endsWith(File.separator)) {
                destPath += File.separator;
            }
            // 文件夹不存在创建
            File file = new File(destPath);
            if (!file.exists()) {
                file.mkdirs();
            }
            String desFilePath = destPath + fileName;
            String absolutepath = String.valueOf(data.get("absolutepath"));
            createPDF(html, desFilePath, absolutepath);
            // imageUrl     水印图片地址
            String imageUrl = null != data.get("waterPath") ? String.valueOf(data.get("waterPath")) : "";
            if (StringUtils.isNotBlank(imageUrl)) {
                watermark(desFilePath, imageUrl);
            }
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
        }
        return flag;
    }


    /**
     * freemarker渲染html
     */
    public static String freeMarkerRender(Map<String, Object> data, String htmlTmp) {
        StringWriter writer = new StringWriter();
        try {
            // 获取模板,并设置编码方式
            Template template = config.getTemplate(htmlTmp, "UTF-8");
            template.setEncoding("UTF-8");
            // 合并数据模型与模板
            template.process(data, writer); //将合并后的数据和模板写入到流中，这里使用的字符流
            writer.flush();
            return writer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                writer.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 生成PDF
     *
     * @param html           html字符串
     * @param targetFilePath 目标路径 + 文件名
     * @return 生成文件的名称
     * @throws Exception e
     */
    public static void createPDF(String html, String targetFilePath, String aboupath) throws Exception {
        if (StringUtils.isBlank(html)) {
            return;
        }
        FileOutputStream outFile = new FileOutputStream(targetFilePath);
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocumentFromString(html);

        //解决图片相对路径的问题
        if (StringUtils.isNotBlank(aboupath)) {
            renderer.getSharedContext().setBaseURL("file:/" + aboupath);
        }

        // 解决中文支持问题
        ITextFontResolver fontResolver = renderer.getFontResolver();
        fontResolver.addFont(SourceHanSansCN_Regular_TTF, "SourceHanSansCN", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, null);
        fontResolver.addFont(FONT_PATH_SONG, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        renderer.layout();
        renderer.createPDF(outFile);
    }


    /**
     * 渲染文件
     *
     * @param filePath PDF文件路径
     * @param imageUrl 水印图片URL
     */
    public static void watermark(String filePath, String imageUrl) {

        InputStream inputStream = null;
        try {

            inputStream = new FileInputStream(filePath);
            PdfReader reader = new PdfReader(inputStream);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(filePath));

            try {
                PdfGState gs1 = new PdfGState();
                gs1.setFillOpacity(0.5f);

                URL url = new URL(imageUrl);
                InputStream fin = url.openStream();

                Image image = Image.getInstance(IOUtils.toByteArray(fin));
                int n = reader.getNumberOfPages();
                for (int i = 1; i <= n; i++) {
                    PdfContentByte pdfContentByte = stamper.getOverContent(i);
                    pdfContentByte.setGState(gs1);

                    float pageHeight = reader.getPageSize(i).getHeight();
                    float pageWidth = reader.getPageSize(i).getWidth();

                    image.setScaleToFitHeight(false);
                    image.scaleToFit(pageWidth, pageHeight);
                    image.setAbsolutePosition(0, 0);
                    pdfContentByte.addImage(image);

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            stamper.close();
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
